﻿using Core.DataAccess.Model.Project.Entrepot;
using Core.Framework.EntityExtend;
using Core.Framework.Model.Common;
using Core.Framework.Util;
using Core.IBusiness.IEntrepotModule;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Core.Business.EntrepotModule
{
    public class Entrepot : IEntrepot
    {

        /// <summary>
        /// 分类操作
        /// </summary>
        /// <param name="model"></param>
        /// <param name="sqlExecType"></param>
        /// <returns></returns>
        public MethodResult<int> ProductTypeExec(ProductType model, SqlExecType sqlExecType)
        {
            return Utils.SqlExecType<ProjectEntrepotContext, ProductType>(model,
                sqlExecType,
                a => a.Id == model.Id);
        }


        public MethodResult<int> ConfirmProductTemplate(int temp_key, string project_token)
        {
            try
            {
                using (var context = new ProjectEntrepotContext())
                {
                    context
                        .ProductTemplate
                        .BulkUpdate(new ProductTemplate
                        {
                            Confirm = true
                        })
                        .Where(a => a.Id == temp_key && a.ProjectToken == project_token);

                    int row = context.BeginSaveChanges(out string error);

                    return new MethodResult<int> { IsFinished = string.IsNullOrWhiteSpace(error), Date = row, Discription = error };
                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Date = 0, Discription = e.Message };
            }

        }


        public MethodResult<int> DicContentExec(ProductParamsDic model, SqlExecType sqlExecType)
        {
            try
            {
                int row = 0;

                string error = string.Empty;

                using (var context = new ProjectEntrepotContext())
                {
                    switch (sqlExecType)
                    {
                        case SqlExecType.insert:
                            context
                                .ProductParamsDic
                                .Add(model);

                            row = context.SaveChanges();
                            break;

                        case SqlExecType.update:
                            int Id = model.Id;
                            string project_token = model.ProjectToken;

                            model.ProjectToken = null;

                            context
                                .ProductParamsDic
                                .BulkUpdate(model)
                                .Where(a => a.Id == Id && a.ProjectToken == project_token);

                            row = context.BeginSaveChanges(out error);
                            break;

                        case SqlExecType.delete:
                            context
                                .ProductParamsDic
                                .Delete(a => a.Id == model.Id && a.ProjectToken == model.ProjectToken);

                            row = context.BeginSaveChanges(out error);
                            break;
                    }
                }

                return new MethodResult<int> { IsFinished = string.IsNullOrWhiteSpace(error), Date = row, Discription = error };
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Date = 0, Discription = e.Message };
            }
        }

        public MethodResult<int> DicTitleExec(ProductParams model, SqlExecType sqlExecType)
        {
            try
            {
                int row = 0;
                string error = string.Empty;

                using (var context = new ProjectEntrepotContext())
                {
                    switch (sqlExecType)
                    {
                        case SqlExecType.insert:
                            context
                                .ProductParams
                                .Add(model);

                            row = context.SaveChanges();
                            break;

                        case SqlExecType.update:
                            int Id = model.Id;
                            string project_token = model.ProjectToken;

                            model.ProjectToken = null;

                            context
                                .ProductParams
                                .BulkUpdate(model)
                                .Where(a => a.Id == Id && a.ProjectToken == project_token);

                            row = context.BeginSaveChanges(out error);
                            break;

                        case SqlExecType.delete:
                            context
                                .ProductParams
                                .Delete(a => a.Id == model.Id && a.ProjectToken == model.ProjectToken);

                            context
                                .ProductParamsDic
                                .Delete(a => a.ParamsKey == model.Id && a.ProjectToken == model.ProjectToken);

                            row = context.BeginSaveChanges(out error);
                            break;
                    }
                }

                return new MethodResult<int> { IsFinished = string.IsNullOrWhiteSpace(error), Date = row, Discription = error };



            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Date = 0, Discription = e.Message };
            }
        }

        public MethodResult<List<ProductParams>> GerDicContent(string project_token, Pagination pagination)
        {
            using (var context = new ProjectEntrepotContext())
            {
                var query = context
                    .ProductParams
                    .Where(a => a.ProjectToken == project_token)
                    .Pagination(pagination);

                return new MethodResult<List<ProductParams>> { IsFinished = true, Date = query };
            }
        }

        public MethodResult<ProductParams> GerDicItemContent(int param_key, string project_token)
        {
            using (var context = new ProjectEntrepotContext())
            {
                var query = context
                    .ProductParams
                    .Where(a => a.Id == param_key && a.ProjectToken == project_token)
                    .FirstOrDefault();

                if (query?.Id > 0)
                {
                    query.ProductParamsDics =
                        context
                            .ProductParamsDic
                            .Where(a => a.ParamsKey == query.Id)
                            .ToList();
                }

                return new MethodResult<ProductParams> { IsFinished = true, Date = query };
            }
        }

        public MethodResult<ProductTemplate> GetItemProductTemplate(int temp_key, string project_token)
        {
            using (var context = new ProjectEntrepotContext())
            {
                var query = context
                    .ProductTemplate
                    .Where(a => a.Id == temp_key && a.ProjectToken == project_token)
                    .FirstOrDefault();

                if (query?.Id > 0)
                {
                    query.ProductSkus =
                        context
                            .ProductSku
                            .Where(a => a.TemplateKey == query.Id)
                            .ToList();

                    query.ProductAttrbutes =
                        context
                            .ProductAttrbute
                            .Where(a => a.ProductId == query.Id)
                            .ToList();

                }

                return new MethodResult<ProductTemplate> { IsFinished = true, Date = query };
            }
        }

        public MethodResult<ProductType> GetProductItemType(int type_key, string project_token)
        {
            using (var context = new ProjectEntrepotContext())
            {
                var query = context
                    .ProductType
                    .Where(a => (a.Id == type_key || a.UpKey == type_key || a.TopKey == type_key) && a.ProjectToken == project_token)
                    .ToList();

                if (query.Count > 0)
                {
                    var entity = query.Where(a => a.Id == type_key).FirstOrDefault();

                    entity.ChildNodes = TypeTree(entity.ChildNodes, entity.Id, query);

                    return new MethodResult<ProductType> { IsFinished = true, Date = entity };
                }
                else
                {
                    return new MethodResult<ProductType> { IsFinished = true, Date = null };
                }

            }
        }

        public MethodResult<List<ProductTemplate>> GetProductTemplate(int type_key, string project_token, Pagination pagination)
        {
            List<ProductTemplate> sources;
            List<ProductSku> skus;
            List<ProductAttrbute> attrs;

            using (var context = new ProjectEntrepotContext())
            {
                sources = context
                    .ProductTemplate
                    .Where(a => a.TypeKey == type_key && a.ProjectToken == project_token)
                    .Pagination(pagination);

                if (sources.Count > 0)
                {
                    var temps = sources.Select(a => a.Id);

                    skus =
                        context
                            .ProductSku
                            .Where(a => temps.Contains(a.TemplateKey))
                            .ToList();

                    attrs =
                        context
                            .ProductAttrbute
                            .Where(a => temps.Contains(a.ProductId))
                            .ToList();
                }
                else
                {
                    skus = new List<ProductSku>();
                    attrs = new List<ProductAttrbute>();
                }

            }

            if (sources?.Count > 0 && skus?.Count > 0)
                foreach (var temp in sources)
                {
                    temp.ProductSkus = skus.Where(a => a.TemplateKey == temp.Id).ToList();
                    if (attrs?.Count > 0)
                        temp.ProductAttrbutes = attrs.Where(a => a.ProductId == temp.Id).ToList();
                    //foreach (var sku in skus)
                    //{
                    //    if (temp.Id == sku.TemplateKey)
                    //    {
                    //        temp.ProductSkus.Add(sku);
                    //    }
                    //}
                }

            return new MethodResult<List<ProductTemplate>> { IsFinished = true, Date = sources };

        }

        public MethodResult<List<ProductType>> GetProductType(string project_token, Pagination pagination)
        {
            List<ProductType> sources;
            List<ProductType> types;

            using (var context = new ProjectEntrepotContext())
            {
                sources = context
                    .ProductType
                    .Where(a => a.ProjectToken == project_token && a.UpKey == 0)
                    .Pagination(pagination);

                if (sources.Count > 0)
                {
                    var keys = sources.Select(a => a.Id);

                    types =
                        context
                            .ProductType
                            .Where(a => keys.Contains(a.TopKey))
                            .ToList();
                }
                else
                    types = new List<ProductType>();
            }

            if (sources.Count > 0 && types.Count > 0)
            {
                foreach (var entity in sources)
                {
                    entity.ChildNodes = TypeTree(entity.ChildNodes, entity.Id, types);
                }
            }

            return new MethodResult<List<ProductType>> { IsFinished = true, Date = sources };
        }

        public MethodResult<List<ProductTemplate>> GetSeachProductTemplate(string title, string project_token, Pagination pagination)
        {
            List<ProductTemplate> sources;
            List<ProductSku> skus;
            List<ProductAttrbute> attrs;

            using (var context = new ProjectEntrepotContext())
            {
                sources = context
                    .ProductTemplate
                    .Where(a => a.Title.Contains(title) && a.ProjectToken == project_token)
                    .Pagination(pagination);

                if (sources.Count > 0)
                {
                    var temps = sources.Select(a => a.Id);

                    skus =
                        context
                            .ProductSku
                            .Where(a => temps.Contains(a.TemplateKey))
                            .ToList();

                    attrs =
                        context
                            .ProductAttrbute
                            .Where(a => temps.Contains(a.ProductId))
                            .ToList();
                }
                else
                {
                    skus = new List<ProductSku>();
                    attrs = new List<ProductAttrbute>();
                }

            }

            if (sources.Count > 0 && skus.Count > 0)
                foreach (var temp in sources)
                {
                    temp.ProductSkus = skus.Where(a => a.TemplateKey == temp.Id).ToList();
                    if (attrs?.Count > 0)
                        temp.ProductAttrbutes = attrs.Where(a => a.ProductId == temp.Id).ToList();

                    //temp.ProductSkus = new List<ProductSku>();
                    //foreach (var sku in skus)
                    //{
                    //    if (temp.Id == sku.TemplateKey)
                    //    {
                    //        temp.ProductSkus.Add(sku);
                    //    }
                    //}
                }

            return new MethodResult<List<ProductTemplate>> { IsFinished = true, Date = sources };
        }

        public MethodResult<int> ProductPurchase(List<ProductPurchase> purchases)
        {
            return AddSKU(purchases);
        }

        public MethodResult<int> ProductReturnGoods(List<ProductPurchase> purchases)
        {
            return AddSKU(purchases);
        }

        private MethodResult<int> AddSKU(List<ProductPurchase> purchases)
        {
            using (var context = new ProjectEntrepotContext())
            {
                context.ProductPurchase.BulkInsert(purchases);

                foreach (var item in purchases)
                {
                    context
                        .ProductSku
                        .BulkUpdate($"count_stock += {item.CountStock}")
                        .Where(a => a.Id == item.SkuKey);
                }

                var row = context.BeginSaveChanges(out string error);

                return new MethodResult<int> { IsFinished = string.IsNullOrWhiteSpace(error), Date = row, Discription = error };
            }

        }

        private MethodResult<int> EeduceSKU(List<ProductSell> purchases)
        {
            using (var context = new ProjectEntrepotContext())
            {
                context.ProductSell.BulkInsert(purchases);

                foreach (var item in purchases)
                {
                    context
                        .ProductSku
                        .BulkUpdate($"count_stock -= {item.CountStock}")
                        .Where(a => a.Id == item.SkuKey);
                }

                var row = context.BeginSaveChanges(out string error);

                return new MethodResult<int> { IsFinished = string.IsNullOrWhiteSpace(error), Date = row, Discription = error };

            }

        }

        public MethodResult<int> ProductSell(List<ProductSell> sells)
        {
            return EeduceSKU(sells);
        }

        public MethodResult<int> ProductSKU(List<ProductSku> skus)
        {
            using (var context = new ProjectEntrepotContext())
            {
                context.ProductSku.BulkInsert(skus);
                var row = context.BeginSaveChanges(out string error);

                return new MethodResult<int> { IsFinished = string.IsNullOrWhiteSpace(error), Date = row, Discription = error };
            }
        }

        public MethodResult<int> ProductTemplateExec(ProductTemplate model, SqlExecType sqlExecType)
        {
            try
            {
                int row = 0;

                string error = string.Empty;

                using (var context = new ProjectEntrepotContext())
                {
                    switch (sqlExecType)
                    {
                        case SqlExecType.insert:


                            context
                                .ProductTemplate
                                .Add(model);


                            // 如果存在库存信息，则插入
                            if (null != model.ProductSkus && model.ProductSkus.Count > 0)
                            {
                                context.SaveChanges();

                                // 验证数据
                                var IsValid = model.ProductSkus.IsValid(IsValidEnum.reg);

                                // 验证失败时返回
                                if (!IsValid.Item1)
                                {
                                    return new MethodResult<int>
                                    {
                                        IsFinished = false,
                                        Discription = IsValid.Item2
                                    };
                                }

                                // 指定供应商
                                foreach (var item in model.ProductSkus)
                                {
                                    item.TemplateKey = model.Id;
                                    item.SupplierKey = model.SupplierKey;
                                }

                                context
                                    .ProductSku
                                    .BulkInsert(model.ProductSkus);

                            }

                            break;

                        case SqlExecType.update:
                            int Id = model.Id;
                            string project_token = model.ProjectToken;

                            model.ProjectToken = null;

                            context
                                .ProductTemplate
                                .BulkUpdate(model)
                                .Where(a => a.Id == Id && a.ProjectToken == project_token);


                            // 如果存在库存信息，则插入
                            if (null != model.ProductSkus && model.ProductSkus.Count > 0)
                            {
                                // 验证数据
                                var IsValid = model.ProductSkus.IsValid(IsValidEnum.update);

                                // 验证失败时返回
                                if (!IsValid.Item1)
                                {
                                    return new MethodResult<int>
                                    {
                                        IsFinished = false,
                                        Discription = IsValid.Item2
                                    };
                                }

                                foreach (var item in model.ProductSkus)
                                {
                                    if (item.Id > 0)
                                    {
                                        context
                                            .ProductSku
                                            .BulkUpdate(item)
                                            .Where(a => a.Id == item.Id);
                                    }
                                    else
                                    {
                                        item.TemplateKey = model.Id;
                                        item.SupplierKey = model.SupplierKey;
                                        context.ProductSku.Add(item);
                                    }

                                }

                            }

                            break;

                        case SqlExecType.delete:
                            context
                                .ProductTemplate
                                .Delete(a => a.Id == model.Id && a.ProjectToken == model.ProjectToken);
                            break;
                    }

                    row = context.BeginSaveChanges(out error);
                }

                return new MethodResult<int> { IsFinished = string.IsNullOrWhiteSpace(error), Date = row, Discription = error };

            }
            catch (Exception e)
            {

                return new MethodResult<int> { IsFinished = false, Date = 0, Discription = e.Message };
            }
        }

        public MethodResult<int> UpdateSKU(decimal sku_key, decimal count_stock)
        {
            using (var context = new ProjectEntrepotContext())
            {
                context
                    .ProductSku
                    .BulkUpdate(new ProductSku
                    {
                        CountStock = count_stock
                    })
                    .Where(a => a.Id == sku_key);

                var row = context.BeginSaveChanges(out string error);

                return new MethodResult<int> { IsFinished = string.IsNullOrWhiteSpace(error), Date = row, Discription = error };

            }
        }

        #region Common

        /// <summary>
        /// 构建树形分类数据
        /// </summary>
        /// <param name="nodes"></param>
        /// <param name="parentID"></param>
        /// <param name="sources"></param>
        List<ProductType> TypeTree(List<ProductType> nodes, int parentID, List<ProductType> sources)
        {
            var tempTree = sources.Where(item => item.UpKey == parentID).ToList();

            if (tempTree.Count > 0)
            {
                nodes = new List<ProductType>();

                foreach (var item in tempTree)
                {
                    nodes.Add(item);
                    item.ChildNodes = TypeTree(item.ChildNodes, item.Id, sources);
                }

                return nodes;
            }

            return null;

        }
        #endregion
    }



}
